package com.bytz.modules.cms.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bytz.common.constant.CommonConstant;
import com.bytz.common.exception.BytzBootException;
import com.bytz.common.system.query.MPJLambdaWrapperEx;
import com.bytz.common.system.query.MPJQueryGenerator;
import com.bytz.modules.cms.common.util.ExcelUtil;
import com.bytz.modules.cms.order.constant.OrderPayConstants;
import com.bytz.modules.cms.order.entity.Order;
import com.bytz.modules.cms.order.entity.OrderPay;
import com.bytz.modules.cms.order.entity.OrderPayDetail;
import com.bytz.modules.cms.order.mapper.OrderPayDetailMapper;
import com.bytz.modules.cms.order.model.OrderBill;
import com.bytz.modules.cms.order.model.OrderBillExcel;
import com.bytz.modules.cms.order.service.IOrderBillService;
import com.bytz.modules.cms.order.service.constants.BillConstants;
import com.bytz.modules.cms.reseller.entity.Reseller;
import com.bytz.modules.cms.user.entity.CmsSysUser;
import com.bytz.modules.cms.user.service.ICmsSysUserService;
import com.bytz.modules.system.dto.EmailDto;
import com.bytz.modules.system.entity.SysDepart;
import com.bytz.modules.system.entity.SysUserDepart;
import com.bytz.modules.system.service.INotifyService;
import com.bytz.modules.system.service.ISysDepartService;
import com.bytz.modules.system.service.ISysUserDepartService;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class OrderBillServiceImpl extends ServiceImpl<OrderPayDetailMapper, OrderPayDetail> implements IOrderBillService {

    @Autowired
    private ICmsSysUserService sysUserService;

    @Autowired
    private INotifyService notifyService;
    @Override
    public IPage<OrderBill> queryPage(Page<OrderBill> requestPage, OrderBill orderBill, Map<String, String[]> parameterMap) throws Exception {
        MPJLambdaWrapperEx<OrderPayDetail> wrapper = MPJQueryGenerator.initQueryWrapper(orderBill, parameterMap, OrderPayDetail.class);
        joinWrapper(wrapper);
        return baseMapper.selectJoinPage(requestPage, OrderBill.class, wrapper);
    }

    @Override
    public OrderBill queryById(String id) throws Exception {
        MPJLambdaWrapper<OrderPayDetail> wrapper = new MPJLambdaWrapper<>();
        joinWrapper(wrapper);
        wrapper.eq(OrderPayDetail::getId, id);
        return baseMapper.selectJoinOne(OrderBill.class, wrapper);
    }

    @Override
    public void sendDailyBill(LocalDateTime date) throws IOException {

        MPJLambdaWrapper<OrderPayDetail> wrapper = new MPJLambdaWrapper<>();
        joinWrapper(wrapper);

        List<OrderBill> orderBills = baseMapper.selectJoinList(OrderBill.class, wrapper
                .eq(OrderPayDetail::getStatus, OrderPayConstants.PayStatus.DONE)
                .eq(OrderPayDetail::getCompleteDate, LocalDateTimeUtil.format(date, "yyyyMMdd"))
        );

        String strDate = LocalDateTimeUtil.format(date, "yyyy年MM月dd日");

        File file = new File(String.format(BillConstants.Email.ATTACH_NAME, strDate));

        List<OrderBillExcel> excelList = BeanUtil.copyToList(orderBills, OrderBillExcel.class);

        try {
            ExcelUtil.exportToOutputStream(BillConstants.Email.ATTACH_SHEET_NAME, OrderBillExcel.class, excelList, FileUtil.getOutputStream(file));


            // 根据departNameCn获取用户
            MPJLambdaWrapper<CmsSysUser> cmsSysUserWrapper = new MPJLambdaWrapper<>();
            cmsSysUserWrapper.select(CmsSysUser::getId, CmsSysUser::getEmail)
                    .leftJoin(SysUserDepart.class, SysUserDepart::getUserId, CmsSysUser::getId)
                    .leftJoin(SysDepart.class, SysDepart::getId, SysUserDepart::getDepId)
                    .eq(SysDepart::getDepartNameCn, BillConstants.Email.RECEIVABLES);
            Set<String> emails = sysUserService.selectJoinList(CmsSysUser.class, cmsSysUserWrapper).stream().map(CmsSysUser::getEmail).filter(StringUtils::isNotBlank).collect(Collectors.toSet());

            EmailDto emailDto = new EmailDto();
            emailDto.setTos(emails);
            emailDto.setSubject(BillConstants.Email.SUBJECT);
            emailDto.setContent(String.format(BillConstants.Email.CONTEXT, strDate));
            emailDto.setAttachments(Lists.newArrayList(file));
            notifyService.sendEmail(emailDto);
        } catch (Exception e) {
            throw new BytzBootException(e);
        }
    }

    @Override
    public void exportXls(HttpServletResponse response, OrderBill orderBill, Map<String, String[]> parameterMap) throws Exception {
        MPJLambdaWrapperEx<OrderPayDetail> wrapper = MPJQueryGenerator.initQueryWrapper(orderBill, parameterMap, OrderPayDetail.class);
        joinWrapper(wrapper);
        List<OrderBill> orderBills = baseMapper.selectJoinList(OrderBill.class, wrapper);

        String strDate = LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy年MM月dd日");
        List<OrderBillExcel> excelList = BeanUtil.copyToList(orderBills, OrderBillExcel.class);

        ExcelUtil.export(
                String.format(BillConstants.Email.ATTACH_NAME, strDate),
                OrderBillExcel.class,
                response,
                excelList
        );
    }

    private void joinWrapper(MPJLambdaWrapper<OrderPayDetail> wrapper) {
        wrapper.selectAll(OrderPayDetail.class)
                .selectAs(Order::getStatus, OrderBill::getOrderStatus)
                .selectAs(OrderPayDetail::getStatus, OrderBill::getPayStatus)
                .select(Order::getResellerId,
                        Order::getOrderNumber,
                        Order::getContractNumber,
                        Order::getSalesId,
                        Order::getSalesName,
                        Order::getDemanderNumber,
                        Order::getDemanderName,
                        Order::getSalesExternalId)
                .select(Reseller::getResellerName)
                .select(OrderPay::getPayType)
                .innerJoin(Order.class, Order::getId, OrderPayDetail::getOrderId)
                .innerJoin(Reseller.class, Reseller::getId, Order::getResellerId)
                .innerJoin(OrderPay.class, OrderPay::getId, OrderPayDetail::getOrderPayId)
                .eq(Order::getDelFlag, CommonConstant.DEL_FLAG_0)
                .eq(Reseller::getDelFlag, CommonConstant.DEL_FLAG_0)
                .eq(OrderPay::getDelFlag, CommonConstant.DEL_FLAG_0);
    }
}
